package com.geng.demo.schedule;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.geng.demo.constant.ContsantWorkFLow;
import com.geng.demo.domain.pojo.hdata.HLodge;
import com.geng.demo.domain.pojo.oa.FormtableMain843Dt1;
import com.geng.demo.domain.pojo.oa.Hrmresource;
import com.geng.demo.mybatisplus.hdata.HLodgeMapper;
import com.geng.demo.mybatisplus.oa.FormtableMain843Dt1Mapper;
import com.geng.demo.mybatisplus.oa.HrmresourceMapper;
import com.geng.demo.util.OASendUtil;
import com.geng.demo.util.TokenUtil;
import com.geng.demo.util.WechatUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class MyScheduledTasks {

    private static final Logger logger = LogManager.getLogger(MyScheduledTasks.class);

    @Autowired
    TokenUtil tokenUtil;

    @Value("${oa.ip}")
    private String ip;

    @Autowired
    private HLodgeMapper hLodgeMapper;

    @Autowired
    private FormtableMain843Dt1Mapper formtableMain843Dt1Mapper;

    //@Scheduled(cron = "0 0 9 * * ?") //每天早上九点执行定时任务
    @Scheduled(fixedDelay = 60000)  // 每隔 1分钟执行一次（单位：毫秒）
    public void asyncHdata() throws CloneNotSupportedException {
        sendSelectMessage();

        DateTimeFormatter yyyy_MM_dd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter yyyy_MM_dd_HHmm = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        //查询2天以内的，且存在智慧园区唯一标识的，且不在OA明细表 formtable_main_843_dt1 中的数据（根据唯一标识判断）
        LocalDateTime queryEndDate = LocalDateTime.now();
        LocalDateTime queryStartDate = queryEndDate.minusDays(2);
        Timestamp timestampStart = Timestamp.valueOf(queryStartDate);
        Timestamp timestampEnd = Timestamp.valueOf(queryEndDate);

        Map<String, Object> params = new HashMap<>();
        params.put("startTime", timestampStart);
        params.put("endTime", timestampEnd);

        List<HLodge> hLodges = hLodgeMapper.selectBetweenOutTime(params);
        if(ObjectUtil.isEmpty(hLodges)){
            return;
        }
        List<HLodge> newHLodges = new ArrayList<>();
        for (HLodge hLodge : hLodges) {
            hLodge.convertParam();  //转换timestamp至LocalDateTime
            String remark = hLodge.getRemark();
            if(remark.contains(",")){
                String[] split = remark.split(",");
                for (int i = 0; i < split.length; i++) {
                    if(i==0){
                        hLodge.setRemark(split[i]);
                        newHLodges.add(hLodge);
                    }else{
                        HLodge hLodge1 = hLodge.clone();
                        String guest = hLodge1.getGuest() + i;
                        hLodge1.setGuest(guest);
                        newHLodges.add(hLodge1);
                    }
                }
            }else{
                newHLodges.add(hLodge);
            }
        }


        //查询OA明细表 formtable_main_843_dt1 中的数据
        List<FormtableMain843Dt1> formtableMain843Dt1s = formtableMain843Dt1Mapper.selectAll();

        List<String> oaDetailList = new ArrayList<>();  //OA流程中已经存在的销卡数据
        if(ObjectUtil.isNotEmpty(formtableMain843Dt1s)){
            oaDetailList = formtableMain843Dt1s.stream().map(x -> x.getZhyqddid()).distinct().collect(Collectors.toList());
        }

        //补充一下退住之后又重新入住后又退住的情况，就是会出现重复的智慧园区订单id，按照卡片注销时间过滤掉已创建并退住过的数据
        List<String> aOaDetailList = oaDetailList;
        List<HLodge> neverHLodges = newHLodges.stream().filter(x -> !aOaDetailList.contains(x.getRemark())).collect(Collectors.toList());
        List<HLodge> yuHLodges = newHLodges.stream().filter(x -> aOaDetailList.contains(x.getRemark())).collect(Collectors.toList());
        List<HLodge> syList = new ArrayList<>();
        if(ObjectUtil.isNotEmpty(yuHLodges)){
            List<String> remarkList = yuHLodges.stream().map(x -> x.getRemark()).collect(Collectors.toList());
            List<FormtableMain843Dt1> compareOaList = formtableMain843Dt1s.stream().filter(x -> remarkList.contains(x.getZhyqddid())).collect(Collectors.toList());
            for (HLodge yuHLodge : yuHLodges) {
                String remark = yuHLodge.getRemark();
                LocalDateTime outtimeLocal = yuHLodge.getOuttimeLocal().minusMinutes(2);
                String kpzxsj = compareOaList.stream().filter(x -> x.getZhyqddid().equals(remark))
                        .findAny().get().getKpzxsj();
                LocalDateTime kpzxsjLocalDateTime = LocalDateTime.parse(kpzxsj, yyyy_MM_dd_HHmm);
                if(outtimeLocal.isAfter(kpzxsjLocalDateTime)){
                    syList.add(yuHLodge);
                }
            }
        }
        List<HLodge> finalHLodges = mergeLists(neverHLodges, syList);
        if(ObjectUtil.isEmpty(finalHLodges)){
            return;
        }

        //获取OA的tokon
        Map<String, String> tokenMap = tokenUtil.gainCacheToken(ip);
        String appId = tokenMap.get("appId");
        String pubKey = tokenMap.get("pubKey");
        String userIdSecret = TokenUtil.encryptCode(pubKey, ContsantWorkFLow.XTTJ);
        String createWorkflowUrl = ip+":83/api/workflow/paService/doCreateRequest";  //创建OA流程的URL

        //创建流程，300条一个流程，避免同时过多数据
        Map<String, Object> param = new HashMap<>();
        String requestName = "35.Xzl-门锁系统销卡同步智慧园区记录流程（自动任务）:创建日期"+queryEndDate.format(yyyy_MM_dd);
        param.put("requestName", requestName); // 流程名称
        param.put("workflowId", ContsantWorkFLow.XZL35PRD);  // 该流程编号OA管理员提供
        List<Map<String, Object>> mainParamList = new ArrayList<>();
        mainParamList.add(OASendUtil.fieldParam("cjsj", queryEndDate.format(yyyy_MM_dd_HHmm)));  //创建日期
        param.put("mainData", mainParamList);
        List<Map<String, Object>> detailParamList = new ArrayList<>();
        List<List<HLodge>> lists = OASendUtil.splitList(finalHLodges, 300);
        for (List<HLodge> list : lists) {
            Map<String, Object> dt1 = new HashMap<>();
            List<Map<String, Object>> workflowRequestTableRecords = new ArrayList<>();
            for(HLodge hLodge : list){
                Map<String, Object> workflowRequestTableRecordsMap = new HashMap<>();
                List<Map<String, Object>> workflowRequestTableFields = new ArrayList<>();
                workflowRequestTableFields.add(OASendUtil.fieldParam("xm", hLodge.getGuest()));
                workflowRequestTableFields.add(OASendUtil.fieldParam("zhyqddid", hLodge.getRemark()));
                workflowRequestTableFields.add(OASendUtil.fieldParam("kpyxq", hLodge.getIntimeLocal().format(yyyy_MM_dd_HHmm)));
                workflowRequestTableFields.add(OASendUtil.fieldParam("kpzxsj", hLodge.getOuttimeLocal().format(yyyy_MM_dd_HHmm)));
                workflowRequestTableFields.add(OASendUtil.fieldParam("fjh", hLodge.getRoomname()));
                workflowRequestTableRecordsMap.put("recordOrder", 0);
                workflowRequestTableRecordsMap.put("workflowRequestTableFields", workflowRequestTableFields);
                workflowRequestTableRecords.add(workflowRequestTableRecordsMap);
            }
            dt1.put("workflowRequestTableRecords", workflowRequestTableRecords);
            dt1.put("tableDBName", ContsantWorkFLow.FORMTABLE_MAIN_843_DT1);
            detailParamList.add(dt1);
            param.put("detailData", detailParamList);
            String resultJson = OASendUtil.sendWorkflow(createWorkflowUrl, userIdSecret, tokenUtil.gainCacheToken(ip).get("token"), appId, param);
            logger.info("resultJson: "+resultJson);
            JSONObject createWorkflowJsonObject = new JSONObject(resultJson);
            String code = createWorkflowJsonObject.getStr("code");
            if(!"SUCCESS".equals(code)){
                logger.info("=asyncHdata=创建"+requestName+"失败："+ JSONUtil.toJsonStr(resultJson));
                continue;
            }
        }

    }

    public List<HLodge> mergeLists(List<HLodge> list1, List<HLodge> list2) {
        // 处理null情况（兼容Java 8及以下）
        list1 = (list1 != null) ? list1 : new ArrayList<>();
        list2 = (list2 != null) ? list2 : new ArrayList<>();

        // 创建新集合并合并元素
        List<HLodge> mergedList = new ArrayList<>(list1.size() + list2.size());
        mergedList.addAll(list1);
        mergedList.addAll(list2);

        return mergedList;
    }

    @Autowired
    WechatUtil wechatUtil;

    @Autowired
    HrmresourceMapper hrmresourceMapper;

    /**
     * 门锁系统销卡时，没有智慧园区订单ID的数据时，需要通知到宿舍管理员
     */
    public void sendSelectMessage(){
        //查询门锁系统数据表中待发送信息的销卡数据
        List<HLodge> hLodges = hLodgeMapper.querySendWeChatMessageList();
        if(ObjectUtil.isEmpty(hLodges)){
            return;
        }
        hLodges.forEach(x -> x.convertParam());
        //查询企微消息接收人的userid
        List<Hrmresource> hrmresources = hrmresourceMapper.selectSendWechatList();
        if(ObjectUtil.isEmpty(hrmresources)){
            logger.info("shimge-宿舍管理员（企微通知） 该角色没有人员，无法接收消息");
            return;
        }
        String userid = hrmresources.stream().map(x -> String.valueOf(x.getId())).collect(Collectors.joining("|"));
        //编辑发送文本
        String sendContent = "请关注智慧园区房客退住：";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        for (HLodge hLodge : hLodges) {
            String guest = hLodge.getGuest();
            String roomname = hLodge.getRoomname();
            LocalDateTime outtimeLocal = hLodge.getOuttimeLocal();
            sendContent += " " + guest + "，房间号：" + roomname + "，退房时间：" + outtimeLocal.format(dateTimeFormatter);
        }
        //发送企微数据
        wechatUtil.sendMessage(sendContent, userid);
        //发送成功之后更新数据表H_Lodge 的
        for (HLodge hLodge : hLodges) {
            hLodge.setAddress("企微已通知");
            hLodgeMapper.updateById(hLodge);
        }
        return;

    }


}
